package server.xml;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.List;

public class WebXmlUtil {
    private static final String webappsPath = System.getProperty("user.dir") + File.separator + "webapps" + File.separator;
    private static WebXml defaultWebXml = null;
    public static WebXml getDefaultWebXml() throws DocumentException {
        if (defaultWebXml == null)
            defaultWebXml = parse(new File(System.getProperty("user.dir") + File.separator + "conf", "web.xml"));
        return defaultWebXml;
    }
    public static WebXml parse(String contextName) throws DocumentException {
        String path = webappsPath + contextName + File.separator + "WEB-INF" + File.separator + "web.xml";
        return parse(new File(path));
    }

    public static WebXml parse(File file) throws DocumentException {
        if (!file.exists() || !file.isFile())
            return null;
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(file);
        Element root = document.getRootElement();
        WebXml webXml = new WebXml();
        parseSessionTimeout(root, webXml);
        parseWelcomeFileList(root, webXml);
        parseServletDefs(root, webXml);
        parseServletMappings(root, webXml);
        parseFilterDefs(root, webXml);
        parseFilterMappings(root, webXml);
        parseListeners(root, webXml);
        parseErrorPages(root, webXml);
        return webXml;
    }
    private static void parseSessionTimeout(Element root, WebXml webXml) {
        Element element = root.element("session-config");
        if (element == null)
            return;
        String timeOut = element.elementText("session-timeout");
        if (timeOut == null)
            return;
        webXml.setSessionTimeout(Integer.parseInt(timeOut));
    }
    private static void parseWelcomeFileList(Element root, WebXml webXml) {
        Element element = root.element("welcome-file-list");
        if (element == null)
            return;
        List<Element> elements = element.elements("welcome-file");
        if (elements == null)
            return;
        for (Element e : elements) {
            webXml.addWelcomeFile(e.getTextTrim());
        }
    }
    private static void parseServletDefs(Element root, WebXml webXml) {
        List<Element> servlets = root.elements("servlet");
        if (servlets == null)
            return;
        for (Element servlet : servlets) {
            ServletDef servletDef = new ServletDef();

            servletDef.setServletName(servlet.elementText("servlet-name"));
            servletDef.setServletClass(servlet.elementText("servlet-class"));

            List<Element> initParams = servlet.elements("init-param");
            if (initParams == null)
                continue;
            for (Element param : initParams) {
                servletDef.addInitParam(param.elementText("param-name"), param.elementText("param-value"));
            }

            webXml.addServletDef(servletDef);
        }


    }
    private static void parseServletMappings(Element root, WebXml webXml) {
        List<Element> mappings = root.elements("servlet-mapping");
        if (mappings == null)
            return;
        for (Element mapping : mappings) {
            ServletMap servletMap = new ServletMap();
            servletMap.setServletName(mapping.elementText("servlet-name"));
            List<Element> patterns = mapping.elements("url-pattern");
            if (patterns == null)
                continue;
            for (Element pattern : patterns) {
                servletMap.addUrlPattern(pattern.getTextTrim());
            }
            webXml.addServletMapping(servletMap);
        }

    }
    private static void parseFilterDefs(Element root, WebXml webXml) {
        List<Element> filters = root.elements("filter");
        if (filters == null)
            return;
        for (Element filter : filters) {
            FilterDef filterDef = new FilterDef();
            filterDef.setFilterName(filter.elementText("filter-name"));
            filterDef.setFilterClass(filter.elementText("filter-class"));
            List<Element> params = filter.elements("init-param");
            if (params == null)
                continue;
            for (Element param : params) {
                filterDef.addInitParameter(param.elementText("param-name"), param.elementText("param-value"));
            }
            webXml.addFilterDef(filterDef);
        }

    }
    private static void parseFilterMappings(Element root, WebXml webXml) {
        List<Element> mappings = root.elements("filter-mapping");
        if(mappings == null)
            return;
        for (Element mapping : mappings) {
            FilterMap filterMap = new FilterMap();
            filterMap.setFilterName(mapping.elementText("filter-name"));
            filterMap.setUrlPattern(mapping.elementText("url-pattern"));
            filterMap.setServletName(mapping.elementText("servlet-name"));
            webXml.addFilterMappings(filterMap);
        }
    }
    private static void parseListeners(Element root, WebXml webXml) {
        List<Element> listeners = root.elements("listener");
        if (listeners == null)
            return;
        for (Element listener : listeners) {
            webXml.addListener(listener.elementText("listener-class"));
        }
    }
    private static void parseErrorPages(Element root, WebXml webXml) {
        List<Element> errorPages = root.elements("error-page");
        if (errorPages == null)
            return;
        for (Element errorPage : errorPages) {
            webXml.addErrorPage(Integer.parseInt(errorPage.elementText("error-code")), errorPage.elementText("location"));
        }
    }
}
